package com.service.abolishing.task;


import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.service.abolishing.dao.ApDetailDao;
import com.service.abolishing.dao.CloudCampusInfoDao;
import com.service.abolishing.dao.UserInfoDao;
import com.service.abolishing.dao.UserLoginRecordDao;
import com.service.abolishing.dto.ApDetailDto;
import com.service.abolishing.dto.DeviceDto;
import com.service.abolishing.dto.NceUploadData;
import com.service.abolishing.dto.UserDto;
import com.service.abolishing.entity.ApDetail;
import com.service.abolishing.entity.CloudCampusInfo;
import com.service.abolishing.entity.UserInfo;
import com.service.abolishing.entity.UserLoginRecord;
import com.service.abolishing.rabbitmq.MsgProducer;
import com.service.abolishing.service.CloudCampusInfoService;
import com.service.abolishing.service.JsonDataService;
import com.service.abolishing.util.TransformationIp;
import com.service.config.dto.SiteDto;
import com.service.config.dto.TerminalUserDto;
import com.service.config.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.service.config.constant.Constant.USER_INFO_AI_FISH;
import static com.service.config.utils.DateUtils.YYYY_MM_DD_HH_MM_SS;
import static com.service.config.utils.UuIDUtil.randomNum;


@Slf4j
@Service
@Async
public class ScheduledService {
    @Resource
    RedisUtil redisUtil;
    @Resource
    private CloudCampusInfoDao cloudCampusInfoDao;
    @Resource
    private CloudCampusInfoService cloudCampusInfoService;
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    CloudCampusApi cloudCampusApi;
    @Resource
    private ApDetailDao apDetailDao;
    private final ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();
    private final ExecutorService product = new ThreadPoolExecutor(20,40,200L, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>(),namedThreadFactory);
    @Resource
    private UserLoginRecordDao userLoginRecordDao;
    @Resource
    private MsgProducer msgProducer;
    @Resource
    private JsonDataService jsonDataService;
    /**
     * 用户登录任务
     * @throws Exception
     */
    @Scheduled(cron = "0 0 0/1 * * ?")
    //@Async("taskExecutorConfig")
    public void getLoginUserDispose() throws Exception {
        if (redisUtil.exist(USER_INFO_AI_FISH)) {
            List<UserLoginRecord> userLoginRecordList = new ArrayList<>();
            List list = redisUtil.getList(USER_INFO_AI_FISH);
            redisUtil.delete(USER_INFO_AI_FISH);
            for (Object o : list) {
                UserDto userDto = JsonXMLUtils.json2obj(o.toString(), UserDto.class);
                UserLoginRecord userLoginRecord = new UserLoginRecord();
                userLoginRecord.setUserId(userDto.getId());
                userLoginRecord.setDate(userDto.getDate());
                userLoginRecord.setOffTime(userDto.getOffTime());
                userLoginRecord.setOnlineTime(userDto.getOnlineTime());
                userLoginRecord.setUsername(userDto.getUsername());
                userLoginRecord.setIp(userDto.getIp());
                userLoginRecord.setTelephone(userDto.getTelephone());
                userLoginRecord.setAddTime(userDto.getAddTime());
                userLoginRecordList.add(userLoginRecord);
                userLoginRecord.setId(IdUtil.getStringId());
            }
            if (userLoginRecordList.size()>0) {
                userLoginRecordDao.insertBatch(userLoginRecordList) ;
            }
        }
    }
    /**
     * 用户定位数据
     * @throws Exception
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    //@Async("taskExecutorConfig")
    public void getLoginUserDispose12() throws Exception {
        String s = PropertiesUtils.readJsonFile("data.json");
        Result result = JsonXMLUtils.json2obj(s,Result.class);
        NceUploadData nceUploadData = JsonXMLUtils.json2obj(result.getData().toString(), NceUploadData.class);
        String secret = nceUploadData.getSecret();
        CloudCampusInfo cloudCampusInfo = cloudCampusInfoService.queryBySecret(secret);
        //校验secret与预设是否相符
        if (cloudCampusInfo == null) {
        }
        jsonDataService.insertList(nceUploadData,cloudCampusInfo);
    }
    /**
     * 定时获取设备列表
     * @throws Exception
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    //@Async("taskExecutorConfig")
    public void getLoginUserDispose1() throws Exception {
        String timeStamp = DateUtil.timeStamp();
        List<CloudCampusInfo> cloudCampusInfos = getCloudCampusInfo();
        List<ApDetail> apDetails = apDetailDao.queryAll(new ApDetail());//拿到所有的数据
        Map<String, List<CloudCampusInfo>> collect = cloudCampusInfos.stream().collect(Collectors.groupingBy(CloudCampusInfo::getManageId));
        collect.forEach((key,values)->{
            List<ApDetail> collect2 = apDetails.stream().filter(apDetail -> apDetail.getManageInfoId().equals(key)).collect(Collectors.toList());
            CountDownLatch latch = new CountDownLatch(values.size());
            List<DeviceDto> devices = new ArrayList<>();
            /*values.forEach(cloudCampusInfo -> {
                //线程池调用
                product.submit(()->{
                    HttpHeaders token = getToken(cloudCampusInfo);
                    List<DeviceDto> deviceDtoList = cloudCampusApi.getDevices(token, cloudCampusInfo);
                    devices.addAll(deviceDtoList);
                    latch.countDown();
                });
            });
            while (true) {
                if (latch.getCount() == 0) {
                    log.info("线程执行完毕");
                    break;
                }
            }*/
            List<DeviceDto> collect1 = devices.stream().filter(TransformationIp.distinctByKey(DeviceDto::getId)).collect(Collectors.toList());
            //removeData(collect1, collect2, values.get(0));
            apDetails.forEach(apDetail -> {
                ApDetailDto apDetailDto = new ApDetailDto();
                apDetailDto.setCount(randomNum(20,100));
                try {
                    redisUtil.zAdd(apDetail.getManageInfoId()+":"+apDetail.getId(), JsonXMLUtils.obj2json(apDetailDto),Integer.parseInt(timeStamp));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                /**
                 * List<CloudCampusInfo> collect3 = values.stream().filter(cloudCampusInfo -> cloudCampusInfo.getId().equals(apDetail.getCloudCampusId())).collect(Collectors.toList());
                 * HttpHeaders token = getToken(collect3.get(0));
                 * msgProducer.getByDeviceTerminalUserList("online", apDetail, token, collect3.get(0),timeStamp);
                 */
            });
        });
    }
    /**
     * 定时获取设备列表
     * @throws Exception
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    @Async("taskExecutorConfig")
    public void getLoginUserDispose2() throws Exception {
        List<CloudCampusInfo> cloudCampusInfos = getCloudCampusInfo();
        List<ApDetail> apDetails = apDetailDao.queryAll(new ApDetail());//拿到所有的数据
        Map<String, List<CloudCampusInfo>> collect = cloudCampusInfos.stream().collect(Collectors.groupingBy(CloudCampusInfo::getManageId));
        collect.forEach((key,values)->{
            List<UserInfo> userInfoList = new ArrayList<>();
            AtomicReference<List<SiteDto>> sites = new AtomicReference<>();
            CountDownLatch latch = new CountDownLatch(values.size());
            values.forEach(cloudCampusInfo -> {
                //线程池调用
                product.submit(()->{
                    HttpHeaders token = getToken(cloudCampusInfo);
                    sites.set(cloudCampusApi.getSites(token, cloudCampusInfo));
                    latch.countDown();
                });
            });
            while (true) {
                if (latch.getCount() == 0) {
                    log.info("线程执行完毕");
                    break;
                }
            }
            List<SiteDto> siteDtoList = sites.get().stream().filter(TransformationIp.distinctByKey(SiteDto::getId)).collect(Collectors.toList());
            siteDtoList.forEach(siteDto -> {
                //线程池调用
                product.submit(()->{
                    List<CloudCampusInfo> collect1 = values.stream().filter(cloudCampusInfo -> cloudCampusInfo.getId().equals(siteDto.getCloudCampusInfoId())).collect(Collectors.toList());
                    if (collect1.size() > 0) {
                        CloudCampusInfo cloudCampusInfo = collect1.stream().findFirst().get();
                        HttpHeaders token = getToken(cloudCampusInfo);
                        Map online = cloudCampusApi.getTerminalUserList("online", siteDto, token, cloudCampusInfo.getDomain());
                        if (online != null) {
                            List<UserInfo> userInfoList1 = getUserInfo(online.get("TerminalUserDto"), cloudCampusInfo);
                            userInfoList.addAll(userInfoList1);
                        }
                    }
                    latch.countDown();
               });
            });
            while (true) {
                if (latch.getCount() == 0) {
                    log.info("线程1执行完毕");
                    break;
                }
            }

            userInfoDao.deleteByManageId(key);
            //更新在新用户
            if (userInfoList.size() > 0) {
                userInfoDao.insertBatch(userInfoList);
            }else {
                UserInfo userInfo = new UserInfo();
                userInfo.setId(IdUtil.getStringId());
                userInfo.setUMac("E4:A7:A0:98:4C:91");
                userInfo.setManageInfoId(apDetails.get(0).getManageInfoId());
                userInfo.setUsername("E4:A7:A0:98:4C:91");
                userInfo.setProbability(50);
                userInfo.setStatus(1);
                userInfoList.add(userInfo);
                userInfo = new UserInfo();
                userInfo.setId(IdUtil.getStringId());
                userInfo.setUMac("E4:A7:A0:98:4C:92");
                userInfo.setManageInfoId(apDetails.get(0).getManageInfoId());
                userInfo.setUsername("E4:A7:A0:98:4C:92");
                userInfo.setProbability(50);
                userInfo.setStatus(1);
                userInfoList.add(userInfo);
                userInfo = new UserInfo();
                userInfo.setId(IdUtil.getStringId());
                userInfo.setUMac("E4:A7:A0:98:4C:93");
                userInfo.setManageInfoId(apDetails.get(0).getManageInfoId());
                userInfo.setUsername("E4:A7:A0:98:4C:93");
                userInfo.setProbability(50);
                userInfo.setStatus(1);
                userInfoList.add(userInfo);
                userInfoDao.insertBatch(userInfoList);
            }
        });
    }

    private  List<CloudCampusInfo> getCloudCampusInfo() {
        List<CloudCampusInfo> cloudCampusInfos = cloudCampusInfoDao.queryAll(new CloudCampusInfo());
        return cloudCampusInfos;

    }

    private List<UserInfo> getUserInfo(Object terminalUserDto,CloudCampusInfo cloudCampusInfo) {
        List<UserInfo> userInfoList = new ArrayList<>();
        List<TerminalUserDto> terminalUserDtoList = ModelMapperUtil.strictMapList(terminalUserDto.toString(), TerminalUserDto.class);
        terminalUserDtoList.forEach(terminalUserDto1 -> {
                UserInfo userInfo = new UserInfo();
                userInfo.setId(IdUtil.getStringId());
                userInfo.setUMac(terminalUserDto1.getTerminalMac());
                userInfo.setManageInfoId(cloudCampusInfo.getManageId());
                userInfo.setUsername(terminalUserDto1.getAccount());
                userInfo.setProbability(50);
                userInfo.setStatus(1);
                userInfo.setLoginTime(DateUtils.dateTime(YYYY_MM_DD_HH_MM_SS,terminalUserDto1.getAccessTime()));
                userInfo.setUIp(terminalUserDto1.getTerminalIP());
                userInfoList.add(userInfo);
            });
        return userInfoList;
    }

    /**
     * 遍历移除
     * @param devices
     * @param apDetails
     * @param cloudCampusInfo
     */
    private List<ApDetail> removeData(List<DeviceDto> devices, List<ApDetail> apDetails,CloudCampusInfo cloudCampusInfo) {
        List<ApDetail> apDetailList = new ArrayList<>();
        //遍历移除
        apDetails.forEach(apDetail -> {
            List<DeviceDto> collect = devices.stream().filter(deviceDto -> deviceDto.getMac().equals(apDetail.getApMac())).collect(Collectors.toList());
            if (collect.size() > 0) {
                devices.removeAll(collect);
            }else {
                apDetailList.add(apDetail);
            }
        });
        if (apDetails.size() > 0) {
            apDetails.removeAll(apDetailList);
            apDetailDao.deleteByIdS(apDetailList);
        }
        if (devices.size()>0){
            List<ApDetail> apDetails1 = ModelMapperUtil.strictMapList(devices, ApDetail.class);
            apDetails1.forEach(apDetail -> {
                apDetail.setDeviceId(apDetail.getId());
                apDetail.setId(IdUtil.getStringId());
                apDetail.setManageInfoId(cloudCampusInfo.getManageId());
                apDetail.setCloudCampusId(cloudCampusInfo.getId());
                apDetail.setUpdateTime(new Date());
                apDetail.setCreateTime(new Date());
            });
            //当存在新的ap点是才进行插入，否则进行更新
            apDetailDao.insertBatch(apDetails1);
            apDetails.addAll(apDetails1);
        }
        return apDetails;
    }
    /**
     * 获取用户token
     * @param cloudCampusInfo
     */
    public HttpHeaders getToken(CloudCampusInfo cloudCampusInfo) {

        HttpHeaders requestHeaders = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        requestHeaders.setContentType(type);
        requestHeaders.add("Accept", MediaType.APPLICATION_JSON.toString());

        String userName = cloudCampusInfo.getTenantName();
        String password = cloudCampusInfo.getTenantPwd();
        String token = "";

        try {
            if (redisUtil.exist(userName.concat("token"))) {
                token = redisUtil.getValue(userName.concat("token"));
            } else {
                //获取token
                token = cloudCampusApi.getToken(userName, password, requestHeaders, cloudCampusInfo.getDomain());
                redisUtil.set(userName.concat("token"), 1, token, 10);
            }
            //获取站点
            requestHeaders.add("X-AUTH-TOKEN", token);
            return requestHeaders;
        } catch (Exception e) {
            log.error("token Access failure!");
            return null;
        }

    }
}


